//
// Created by suzhen on 16-12-9.
//


#ifndef ORIONV2_ORION_H
#define ORIONV2_ORION_H

#include <unistd.h>
#include <glog/logging.h>
#include <string>
#include <list>
#include <openssl/ssl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <uv.h>
#include <cstddef>
#include <functional>
#include <thread>
#include <mutex>
#include <ostream>

#include "boost/fiber/all.hpp"
#include "boost/thread/future.hpp"
#include "boost/fiber/recursive_mutex.hpp"
#include "boost/format.hpp"


using FdType  = int;
using EventFlag = int;
using RawDataType = char;

using ThreadId = std::thread::id;

using HandleContext = uv_handle_t;
using AsyncContext = uv_async_t;
using TimerContext = uv_timer_t;
using CoreLoopContext = uv_loop_t;
using PollContext = uv_poll_t;

#define getCurrentThreadId()  std::this_thread::get_id()

#define YES true
#define NO false

#define LOG_I LOG(INFO)
#define SYS_FAULT(con) CHECK((con)) << "系统断言失败 ----------> "

#define DEFAULT_READ_BUFFER_SIZE 4096

#define DEFAULT_STREAM_IDLE_MS 20 * 1000

#ifdef OSX
#define OPT_NOT_SIG_PIPE SO_NOSIGPIPE
#else
#define OPT_NOT_SIG_PIPE MSG_NOSIGNAL
#endif

#define ORION_V2_NAMESPACE_BEGIN \
    namespace Orion { \
        namespace V2 { \

#define ORION_V2_NAMESPACE_END \
        } \
    } \


#define USING_ORION \
    using namespace Orion;\

#define USING_ORION_V2 \
    using namespace Orion::V2;\

#define ORION_V2 Orion::V2

ORION_V2_NAMESPACE_BEGIN

        class AbstractAsyncStream;

        class AsyncEventGenerator;

        class AsyncEventGeneratorGroup;

        namespace EnhanceSupport {

            class UserDataSupport {
            public:
                virtual ~UserDataSupport() {
                }

            protected:
                void *userData{nullptr};
            public:
                void *getUserData() { return userData; };

                void setUserData(void *udata) {
                    userData = udata;
                }
            };

            /**
             * 支持引用计数,但是,该类禁用了拷贝和移动的所有操作
             *
             * recursive_mutex中的移动和拷贝,是private的
             * 为了更加符合C++0x, MRCSupport 将拷贝和移动均删除
             *
             */
            class MRCSupport {

            public:
                virtual ~MRCSupport() {
                };

                MRCSupport()
                        : refCount_(0),
                          mrcLock_() {

                }

                MRCSupport(const MRCSupport &) = delete;

                MRCSupport &operator=(const MRCSupport &) = delete;

                MRCSupport(MRCSupport &&) = delete;

                MRCSupport &operator=(MRCSupport &&) = delete;

            protected:
                std::size_t refCount_{0};
                std::recursive_mutex mrcLock_{};

            public:
                std::size_t retain() {
                    std::lock_guard<std::recursive_mutex> guard(mrcLock_);
                    return ++refCount_;
                }

                void release() {
                    CHECK(refCount_ > 0) << "当 refCount_ = 0 时,无法继续降低,请检查retain和release调用次数是否相等!";
                    mrcLock_.lock();
                    if (--refCount_ == 0) {
                        mrcLock_.unlock();
                        delete this;
                        return;
                    }
                    mrcLock_.unlock();
                }

                std::size_t getRefCount() const { return refCount_; }
            };
        };

        class TlsConf {

        public:
            TlsConf();

            explicit TlsConf(SSL_CTX *usrCtx);

            TlsConf(const std::string &certFilePath,
                    const std::string &keyFilePath);

            TlsConf(const TlsConf &) = delete;

            TlsConf &operator=(const TlsConf &) = delete;

            TlsConf(TlsConf &&other);

            TlsConf &operator=(TlsConf &&other);

            ~TlsConf();

            SSL_CTX *getNativeSslCtx();

            bool isSslCtxValid() const;

            const std::string &getCertFilePath();

            const std::string &getKeyFilePath();

        private:
            bool isValid_;
            bool passByUser_;
            std::string certFilePath_;
            std::string keyFilePath_;
            SSL_CTX *sslCtxContext_;
        };

        struct Configuration {

            std::string bindAddr{"0.0.0.0"};
            uint bindPort{0};
            size_t maxBackLog{1000};
            int allowReuseAddr{1};
            uint socketIdleMs{DEFAULT_STREAM_IDLE_MS};

            Configuration(const std::string &bindAddr,
                          uint bindPort,
                          size_t maxBackLog,
                          bool allowReuseAddr,
                          uint socketIdleMs);
        };

        //Orion 的全局初始化函数
        extern void OrionInit();


ORION_V2_NAMESPACE_END

#endif //ORIONV2_ORION_H
